﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Entity;
using System.Linq;
using System.Threading.Tasks;
using System.Net;
using System.Web;
using System.Web.Mvc;
using System.Text.RegularExpressions;
using BootyBay.Models;
using BootyBay.Repository;

namespace BootyBay.ServerWebApp
{
    [OutputCache(Duration = 0, VaryByParam = "*", NoStore = true)]
    public class PackageController : Controller
    {

        // GET: /Package/
        public ActionResult Index()
        {
            var apps = ApplicationRepository.Instance().GetAllApplications();
            return View(apps.ToList());
        }

        public ActionResult PackageList(string name)
        {
            name = string.IsNullOrEmpty(name) ? string.Empty : name.Trim();

            var apps = ApplicationRepository.Instance().GetAllApplications(name).ToList();

            ViewBag.SearchWord = name;
            return PartialView("_PackageList", apps);
        }

        [HttpPost]
        public ActionResult RecommendApp(int id, string name)
        {
            var repository = new RepositoryBase<ApplicationInfo>();
            var app = repository.GetByID(id);
            app.IsRecommended = app.IsRecommended ? false : true;
            repository.Update(app);

            name = string.IsNullOrEmpty(name) ? string.Empty : name.Trim();
            var apps = ApplicationRepository.Instance().GetAllApplications(name).ToList();

            ViewBag.SearchWord = name;
            return PartialView("_PackageList", apps);
        }

        [HttpPost]
        public ActionResult RemoveApp(int id, string name)
        {
            var repository = new RepositoryBase<ApplicationInfo>();
            var app = repository.GetByID(id);
            app.IsValid = false;
            repository.Update(app);

            name = string.IsNullOrEmpty(name) ? string.Empty : name.Trim();
            var apps = ApplicationRepository.Instance().GetAllApplications(name).ToList();

            ViewBag.SearchWord = name;
            return PartialView("_PackageList", apps);
        }

        //public Task<ActionResult> PackageList(string name)
        //{
        //    var apps = ApplicationRepository.Instance().GetAllApplications(name);
        //    return PartialView("_PackageList", await apps.ToListAsync());
        //}

        // GET: /Package/Details/5
        public ActionResult Details(int id)
        {
            View_Application app = ApplicationRepository.Instance().GetApplicationById(id);
            if (app == null)
            {
                return HttpNotFound();
            }
            return View(app);
        }

        public ActionResult Hub(int? id)
        {
            var app = new View_Application();
            if (id != null)
            {
                app = ApplicationRepository.Instance().GetApplicationById(id.Value);
            }
            return View("Hub", app);
        }

        [HttpGet]
        public ActionResult ApplicationInfo(int? id, string viewName = "")
        {
            var app = new View_Application();
            if (id != null)
            {
                app = ApplicationRepository.Instance().GetApplicationById(id.Value);

                ViewBag.Status = app.Status;

                var packageList = ApplicationRepository.Instance().GetUploadedPackages(id.Value);
                ViewBag.PackageList = packageList;

                viewName = app.IsPublicApp ? "ApplicationPublicInfo" : "ApplicationInfo";
            }

            RepositoryBase<Category> r = new RepositoryBase<Category>();
            ViewBag.CategoryList = r.GetAll().ToList();

            return View(viewName, app);
        }

        [HttpPost]
        public ActionResult ApplicationInfo(View_Application app, string[] keyword)
        {
            var id = app.Id;
            string keywords = "";
            foreach (var k in keyword)
            {
                var word = k.Trim();
                if (!string.IsNullOrEmpty(word))
                {
                    keywords += word + ";";
                }
            }
            if (id == 0)
            {
                ApplicationInfo appInfo = new ApplicationInfo()
                {
                    Id = 0,
                    ApplicationName = app.ApplicationName,
                    MajorVersion = "",
                    IsHidden = app.IsHidden,
                    IsRecommended = app.IsRecommended,
                    CreationDate = DateTime.UtcNow,
                    OperationDate = DateTime.UtcNow,
                    Status = (int)AppStatus.NotSubmitted,
                    IsPublicApp = false,
                    IsValid = true
                };
                appInfo = ApplicationInfoRepository.Instance().Insert(appInfo);

                ApplicationVersionInfo verInfo = new ApplicationVersionInfo()
                {
                    Id = 0,
                    Id_ApplicationInfo = appInfo.Id,
                    IdentityName = string.Empty,
                    Version = string.Empty,
                    Publisher = string.Empty,
                    DisplayName = string.Empty,
                    PublisherDisplayName = string.Empty,
                    Description = app.Description,
                    ChangeLog = string.Empty,
                    IsInPublicWindowsStore = false,
                    Category = app.Category,
                    Subcategory = 0,
                    OperationDate = DateTime.UtcNow,
                    Keywords = keywords,
                };

                verInfo = ApplicationVersionInfoRepository.Instance().Insert(verInfo);

                id = appInfo.Id;
            }
            else
            {
                var appInfo = ApplicationInfoRepository.Instance().GetByID(id);
                var version = ApplicationVersionInfoRepository.Instance().GetByID(app.Id_ApplicationVersion);

                appInfo.ApplicationName = app.ApplicationName;
                appInfo.IsHidden = app.IsHidden;
                appInfo.IsRecommended = app.IsRecommended;
                appInfo.OperationDate = DateTime.UtcNow;
                appInfo.Status = (int)AppStatus.NotSubmitted;
                ApplicationInfoRepository.Instance().Update(appInfo);

                version.Description = app.Description;
                version.Category = app.Category;
                version.Keywords = keywords;
                version.OperationDate = DateTime.UtcNow;
                ApplicationVersionInfoRepository.Instance().Update(version);
            }

            app = ApplicationRepository.Instance().GetApplicationById(id);

            return ApplicationInfo(id);
        }

        [HttpPost]
        public ActionResult ApplicationPublicInfo(View_Application app, string[] keyword)
        {
            var id = app.Id;
            string keywords = "";
            foreach (var k in keyword)
            {
                var word = k.Trim();
                if (!string.IsNullOrEmpty(word))
                {
                    keywords += word + ";";
                }
            }
            if (id == 0)
            {
                ApplicationInfo appInfo = new ApplicationInfo()
                {
                    Id = 0,
                    ApplicationName = app.ApplicationName,
                    MajorVersion = "",
                    IsHidden = app.IsHidden,
                    IsRecommended = app.IsRecommended,
                    CreationDate = DateTime.UtcNow,
                    OperationDate = DateTime.UtcNow,
                    Status = (int)AppStatus.NotSubmitted,
                    IsPublicApp = true,
                    IsValid = true
                };
                appInfo = ApplicationInfoRepository.Instance().Insert(appInfo);

                ApplicationPublic publicInfo = new ApplicationPublic()
                {
                    Id = 0,
                    Id_ApplicationInfo = appInfo.Id,
                    StoreHttpUrl = app.StoreHttpUrl,
                    Description = app.Description,
                    Category = app.Category,
                    Subcategory = 0,
                    OperationDate = DateTime.UtcNow,
                    Keywords = keywords,
                };

                publicInfo = ApplicationPublicRepository.Instance().Insert(publicInfo);

                id = appInfo.Id;
            }
            else
            {
                var appInfo = ApplicationInfoRepository.Instance().GetByID(id);
                var publicInfo = ApplicationPublicRepository.Instance().GetByID(app.Id_ApplicationVersion);

                appInfo.ApplicationName = app.ApplicationName;
                appInfo.IsHidden = app.IsHidden;
                appInfo.IsRecommended = app.IsRecommended;
                appInfo.OperationDate = DateTime.UtcNow;
                appInfo.Status = (int)AppStatus.PublicStoreApp;
                ApplicationInfoRepository.Instance().Update(appInfo);

                publicInfo.StoreHttpUrl = app.StoreHttpUrl;
                publicInfo.Description = app.Description;
                publicInfo.Category = app.Category;
                publicInfo.Keywords = keywords;
                publicInfo.OperationDate = DateTime.UtcNow;
                ApplicationPublicRepository.Instance().Update(publicInfo);
            }

            app = ApplicationRepository.Instance().GetApplicationById(id);

            return ApplicationInfo(id);
        }

        //[HttpGet]
        //public ActionResult AppSubmission(int id)
        //{
        //    ViewBag.id = id;
        //    var appInfo = ApplicationInfoRepository.Instance().GetByID(id);
        //    ViewBag.Status = appInfo.Status;
        //    var list = ApplicationRepository.Instance().GetUploadedPackages(id);
        //    return View(list);
        //}

        [HttpPost]
        public ActionResult PublishApp(int id)
        {
            var app = ApplicationRepository.Instance().GetApplicationById(id);

            var appInfo = ApplicationInfoRepository.Instance().GetByID(id);
            appInfo.OperationDate = DateTime.UtcNow;
            appInfo.Status = (int)AppStatus.Published;
            ApplicationInfoRepository.Instance().Update(appInfo);

            return Hub(id);
        }

        [HttpPost]
        public ActionResult Uploadimage(int id, int index)
        {
            ApplicationVersionInfo upVersion = new ApplicationVersionInfo();
            ApplicationProcessorArchitecture upArchitecture = new ApplicationProcessorArchitecture();

            if (Request.Files.Count == 0)
            {
                return Json(new { url = string.Empty });
            }

            HttpPostedFileBase file = Request.Files[0];
            if (!file.FileName.ToLower().EndsWith(".png"))
            {
                return Json(new { url = string.Empty });
            }

            var name = Guid.NewGuid().ToString() + ".png";
            var stream = file.InputStream;
            var screenshotUrl = BootyBay.Package.PackageManager.UploadImage(stream, name, file.ContentLength);

            var app = ApplicationRepository.Instance().GetApplicationById(id);
            var version = ApplicationVersionInfoRepository.Instance().GetByID(app.Id_ApplicationVersion);

            if (string.IsNullOrEmpty(version.ScreenshotUrls))
            {
                version.ScreenshotUrls = ";;;;;;;;";
            }

            var urls = version.ScreenshotUrls.Split(';');
            urls[index] = screenshotUrl;

            version.ScreenshotUrls = string.Join(";", urls);
            version.OperationDate = DateTime.UtcNow;

            ApplicationVersionInfoRepository.Instance().Update(version);

            var result = new { url = screenshotUrl };
            return Json(result);
        }

        [HttpPost]
        public ActionResult Upload(int id)
        {
            ApplicationVersionInfo upVersion = new ApplicationVersionInfo();
            ApplicationProcessorArchitecture upArchitecture = new ApplicationProcessorArchitecture();

            var app = ApplicationRepository.Instance().GetApplicationById(id);
            var version = ApplicationVersionInfoRepository.Instance().GetByID(app.Id_ApplicationVersion);

            Version vOld = new Version("0.0.0.0");
            Version vNew = new Version("0.0.0.0");
            if (!string.IsNullOrEmpty(version.Version))
            {
                vOld = new Version(version.Version);
            }

            for (int i = 0; i < Request.Files.Count; i++)
            {
                HttpPostedFileBase file = Request.Files[i];
                var name = file.FileName.Split('\\').Last();
                var stream = file.InputStream;

                if (file.FileName.EndsWith("appx"))
                {
                    Match match = Regex.Match(file.FileName, @"(?<version>\d+\.\d+\.\d+\.\d+)");

                    if (match.Success)
                    {
                        var vString = match.Groups["version"].ToString();
                        vNew = new Version(vString);

                        if (vNew < vOld)
                        {
                            ViewBag.VersionIncorrect = "The version of uploaded package is lower than server, please check.";
                            return PartialView("_SubmissionResult");
                        }
                    }
                    else
                    {
                        ViewBag.VersionIncorrect = "The version of uploaded package is not correct. Make sure the appx file has the currect version format.";
                        return PartialView("_SubmissionResult");
                    }
                }

                string url = string.Empty;
                var uploaded = BootyBay.Package.PackageManager.UploadPackage(stream, app.Id_ApplicationVersion, version.Id, name, file.ContentLength, out url);

                if (uploaded != null)
                {
                    upVersion = uploaded;
                    upArchitecture.PackageLocationUrl = url;
                    upArchitecture.ProcessorArchitecture = upVersion.ApplicationProcessorArchitectures.FirstOrDefault().ProcessorArchitecture;
                }
                else
                {
                    upArchitecture.PackageCertLocationUrl = url;
                }
            }


            Version v_New = new Version(upVersion.Version);

            if (v_New != vNew)
            {
                ViewBag.VersionIncorrect = "The version of uploaded package does not consist with appx name.";
                return PartialView("_SubmissionResult");
            }

            if (vNew < vOld)
            {
                ViewBag.VersionIncorrect = "The version of uploaded package is lower than server, please check.";
                return PartialView("_SubmissionResult");
            }

            version.IdentityName = upVersion.IdentityName;
            version.Version = upVersion.Version;
            version.Publisher = upVersion.Publisher;
            version.DisplayName = upVersion.DisplayName;
            version.PublisherDisplayName = upVersion.PublisherDisplayName;
            version.LogoUrl_Store = upVersion.LogoUrl_Store;
            version.LogoUrl_150x150 = upVersion.LogoUrl_150x150;
            version.LogoUrl_30x30 = upVersion.LogoUrl_30x30;
            version.LogoUrl_310x150 = upVersion.LogoUrl_310x150;
            version.LogoUrl_310x310 = upVersion.LogoUrl_310x310;
            version.LogoUrl_70x70 = upVersion.LogoUrl_70x70;
            version.ProtocolUrl = upVersion.ProtocolUrl;
            version.OperationDate = DateTime.UtcNow;

            ApplicationVersionInfoRepository.Instance().Update(version);

            var architecture = AppArchitectureRepository.Instance().GetByVersionId(version.Id).Where(a => a.ProcessorArchitecture == upArchitecture.ProcessorArchitecture).FirstOrDefault();
            if (architecture == null)
            {
                upArchitecture.Id_ApplicationVersionInfo = version.Id;
                upArchitecture.UploadDate = DateTime.UtcNow;
                AppArchitectureRepository.Instance().Insert(upArchitecture);
            }
            else
            {
                architecture.PackageLocationUrl = upArchitecture.PackageLocationUrl;
                architecture.PackageCertLocationUrl = upArchitecture.PackageCertLocationUrl;
                architecture.ProcessorArchitecture = upArchitecture.ProcessorArchitecture;
                architecture.UploadDate = DateTime.UtcNow;
                AppArchitectureRepository.Instance().Update(architecture);
            }

            var appInfo = ApplicationInfoRepository.Instance().GetByID(id);
            appInfo.MajorVersion = version.Version;
            appInfo.OperationDate = DateTime.UtcNow;
            appInfo.Status = (int)AppStatus.NotPublished;
            ApplicationInfoRepository.Instance().Update(appInfo);

            ViewBag.Successful = "Completed.";
            //return Json(version);
            return PartialView("_SubmissionResult");
        }

        [HttpGet]
        public ActionResult Create()
        {
            ApplicationInfo appinfo = new ApplicationInfo()
            {
                Id = 0,
                ApplicationName = string.Empty,
                MajorVersion = string.Empty,
            };

            return PartialView();
        }

        [HttpGet]
        public ActionResult Category()
        {
            RepositoryBase<Category> repository = new RepositoryBase<Category>();
            var list = repository.GetAll().ToList();

            return View(list);
        }
        [HttpPost]
        public ActionResult Category(Category newCategory)
        {
            RepositoryBase<Category> repository = new RepositoryBase<Category>();
            if (newCategory.Id == 0)
            {
                repository.Insert(newCategory);
                ViewBag.SuccessMessage = "Category added.";
            }
            else
            {
                repository.Update(newCategory);
                ViewBag.SuccessMessage = "Category updated.";
            }

            var list = repository.GetAll().ToList();
            return PartialView("_CategoryList", list);
        }

        [HttpPost]
        public ActionResult DeleteCategory(int id)
        {
            RepositoryBase<Category> repository = new RepositoryBase<Category>();
            var list = new List<Category>();

            var existed = ApplicationRepository.Instance().GetAllApplications().Any(a => a.Category == id);

            if (existed)
            {
                ViewBag.ErrorMessage = "Can not delete, some applications are using this category.";
                list = repository.GetAll().ToList();
                return PartialView("_CategoryList", list);
            }

            var category = repository.GetByID(id);
            repository.Delete(category);
            ViewBag.SuccessMessage = "Category deleted.";

            list = repository.GetAll().ToList();
            return PartialView("_CategoryList", list);
        }

        //// GET: /Package/Create
        //public ActionResult Create()
        //{
        //    ViewBag.Id_ApplicationInfo = new SelectList(db.ApplicationInfoes, "Id", "ApplicationIdentityName");
        //    return View();
        //}

        //// POST: /Package/Create
        //// To protect from overposting attacks, please enable the specific properties you want to bind to, for 
        //// more details see http://go.microsoft.com/fwlink/?LinkId=317598.
        //[HttpPost]
        //[ValidateAntiForgeryToken]
        //public async Task<ActionResult> Create([Bind(Include = "Id,Id_ApplicationInfo,IdentityName,Version,Publisher,ProcessorArchitecture,DisplayName,PublisherDisplayName,Description,ChangeLog,IsInPublicWindowsStore,PackageLocationUrl,PackageCertLocationUrl")] ApplicationVersionInfo applicationversioninfo)
        //{
        //    if (ModelState.IsValid)
        //    {
        //        db.ApplicationVersionInfoes.Add(applicationversioninfo);
        //        await db.SaveChangesAsync();
        //        return RedirectToAction("Index");
        //    }

        //    ViewBag.Id_ApplicationInfo = new SelectList(db.ApplicationInfoes, "Id", "ApplicationIdentityName", applicationversioninfo.Id_ApplicationInfo);
        //    return View(applicationversioninfo);
        //}

        //// GET: /Package/Edit/5
        //public async Task<ActionResult> Edit(int? id)
        //{
        //    if (id == null)
        //    {
        //        return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
        //    }
        //    ApplicationVersionInfo applicationversioninfo = await db.ApplicationVersionInfoes.FindAsync(id);
        //    if (applicationversioninfo == null)
        //    {
        //        return HttpNotFound();
        //    }
        //    ViewBag.Id_ApplicationInfo = new SelectList(db.ApplicationInfoes, "Id", "ApplicationIdentityName", applicationversioninfo.Id_ApplicationInfo);
        //    return View(applicationversioninfo);
        //}

        //// POST: /Package/Edit/5
        //// To protect from overposting attacks, please enable the specific properties you want to bind to, for 
        //// more details see http://go.microsoft.com/fwlink/?LinkId=317598.
        //[HttpPost]
        //[ValidateAntiForgeryToken]
        //public async Task<ActionResult> Edit([Bind(Include = "Id,Id_ApplicationInfo,IdentityName,Version,Publisher,ProcessorArchitecture,DisplayName,PublisherDisplayName,Description,ChangeLog,IsInPublicWindowsStore,PackageLocationUrl,PackageCertLocationUrl")] ApplicationVersionInfo applicationversioninfo)
        //{
        //    if (ModelState.IsValid)
        //    {
        //        db.Entry(applicationversioninfo).State = EntityState.Modified;
        //        await db.SaveChangesAsync();
        //        return RedirectToAction("Index");
        //    }
        //    ViewBag.Id_ApplicationInfo = new SelectList(db.ApplicationInfoes, "Id", "ApplicationIdentityName", applicationversioninfo.Id_ApplicationInfo);
        //    return View(applicationversioninfo);
        //}

        //// GET: /Package/Delete/5
        //public async Task<ActionResult> Delete(int? id)
        //{
        //    if (id == null)
        //    {
        //        return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
        //    }
        //    ApplicationVersionInfo applicationversioninfo = await db.ApplicationVersionInfoes.FindAsync(id);
        //    if (applicationversioninfo == null)
        //    {
        //        return HttpNotFound();
        //    }
        //    return View(applicationversioninfo);
        //}

        //// POST: /Package/Delete/5
        //[HttpPost, ActionName("Delete")]
        //[ValidateAntiForgeryToken]
        //public async Task<ActionResult> DeleteConfirmed(int id)
        //{
        //    ApplicationVersionInfo applicationversioninfo = await db.ApplicationVersionInfoes.FindAsync(id);
        //    db.ApplicationVersionInfoes.Remove(applicationversioninfo);
        //    await db.SaveChangesAsync();
        //    return RedirectToAction("Index");
        //}

        //protected override void Dispose(bool disposing)
        //{
        //    if (disposing)
        //    {
        //        db.Dispose();
        //    }
        //    base.Dispose(disposing);
        //}
    }
}
